package ar.edu.uba.fi.jmit.monitorengine.core.rangeobserver;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import ar.edu.uba.fi.jmit.integrationcommons.Event;
import ar.edu.uba.fi.jmit.integrationcommons.EventPriority;
import ar.edu.uba.fi.jmit.monitorengine.Constants;
import ar.edu.uba.fi.jmit.monitorengine.MonitorEngineTestCase;
import ar.edu.uba.fi.jmit.monitorengine.ResourceProperties;
import ar.edu.uba.fi.jmit.monitorengine.core.ConfigurationManager;
import ar.edu.uba.fi.jmit.monitorengine.core.monitor.MethodInvocationCounterMonitor;
import ar.edu.uba.fi.jmit.monitorengine.mock.ConfigurationManagerMock;
import ar.edu.uba.fi.jmit.monitorengine.mock.MonitorEngineSenderMock;

public class MethodInvocationCounterRangeObserverTestCase extends
		MonitorEngineTestCase {

	private MethodInvocationCounterMonitor monitor;
	private MonitorEngineSenderMock monitorEngineSender;
	
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		monitor = new MethodInvocationCounterMonitor();
		monitorEngineSender = new MonitorEngineSenderMock();
		ConfigurationManagerMock.useMockConfigurationManager();
		ConfigurationManagerMock.addMonitorApplication("testMonitor", "application");
		ConfigurationManagerMock.addMonitorType("testMonitor", "FieldValue");
		Map<String, String> monitorConfiguration = new HashMap<String, String>();
		monitorConfiguration.put("methodConfiguration.method.name", "someMethod");
		monitorConfiguration.put("methodConfiguration.method.class", "some.package.SomeClas");
		monitorConfiguration.put("methodConfiguration.method.id", "x");
		ConfigurationManager.getInstance().addConfiguration("testMonitor", monitorConfiguration);
		monitor.setMonitorEngineSender(new MonitorEngineSenderMock());//uses another one
		monitor.init(ConfigurationManager.getInstance().getConfiguration("testMonitor"));
	}
	
	public void testMaxBoundExceded() {
		MethodInvocationCounterRangeObserver rangeObserver = new MethodInvocationCounterRangeObserver();
		monitor.addRangeObserver(rangeObserver);
		rangeObserver.setMonitorEngineSender(monitorEngineSender);
		rangeObserver.setMaxValue(20L);
		rangeObserver.setMinValue(null);
		rangeObserver.setName("testRange");
		rangeObserver.setAlert(true);
		rangeObserver.setSeverity("This is not a big problem, just a test");
		rangeObserver.setTimeOutOfRangeAllowed(null);
		for(int i = 0; i < 15; i++) {
			monitor.execute(this.createEvent());
		}
		assertEquals(0, monitorEngineSender.getSendedEvents().size());
		for(int i = 0; i < 6; i++) {
			monitor.execute(this.createEvent());
		}
		assertEquals(1, monitorEngineSender.getSendedEvents().size());
		Event event = monitorEngineSender.getLastSendedEvent();
		assertEquals(MethodInvocationCounterRangeObserver.class.getName(), event.getSource());
		assertEquals(EventPriority.ALERT, event.getPriority());
		assertEquals("testRange", event.getData().get(ResourceProperties.getProperty(Constants.RANGE_NAME)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.RANGE_EXCEDED_BOUND)));
		assertEquals(21L, event.getData().get(ResourceProperties.getProperty(Constants.RANGE_REGISTERED_VALUE)));
		assertEquals("This is not a big problem, just a test", event.getData().get(ResourceProperties.getProperty(Constants.RANGE_SEVERITY)));
		assertEquals("someMethod(...)", event.getData().get(ResourceProperties.getProperty(Constants.RANGE_MONITORED_METHOD)));
		assertEquals("some.package.SomeClas", event.getData().get(ResourceProperties.getProperty(Constants.RANGE_MONITORED_CLASS)));
		assertEquals("3", event.getData().get(ResourceProperties.getProperty(Constants.RANGE_MONITORED_OBJECT)));
	}
		
	private Event createEvent() {
		Event event = new Event();
		event.setSource("testRange");
		event.addData(ResourceProperties.getProperty(Constants.EVENT_OBJECT_ID), "3");
		event.addData(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY), "\"testMonitor\"");
		event.addData(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE), new Date());
		return event;
	}
}
